#include "stdafx.h"

#include "WordProxy.h"
#include "MSWORD9.H"

LPCWSTR cWordApplicationProgID = L"Word.Application";


CWordProxy::CWordProxy() : m_WordApplication(NULL), m_Document(NULL)
{
}

void CWordProxy::Initialize()
{
	_ASSERT( m_WordApplication == NULL);

	CLSID clsId = {0};
	HRESULT hr = CLSIDFromProgID(cWordApplicationProgID, &clsId); 
	if (hr != S_OK)
		throw EIinitializationError(hr);
	
	hr = CoCreateInstance(clsId, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (LPVOID*)&m_WordApplication);
	if (hr != S_OK)
		throw EIinitializationError(hr);
}

DISPID CWordProxy::GetDispID(IDispatch* pIDispatch, const CComBSTR& Name)
{
	_ASSERT( pIDispatch != NULL );

	DISPID DispId = 0;
	HRESULT hr = pIDispatch->GetIDsOfNames(IID_NULL, (LPOLESTR*)&Name, 1, GetUserDefaultLCID(), &DispId); 
	if( hr != S_OK)
		throw EInvocationError(hr);
	return DispId;
}

DISPPARAMS CWordProxy::CreateDispParams(CComVariant& Param)
{
	DISPPARAMS dispParams = {0};
	
	dispParams.cArgs = 1;
	dispParams.rgvarg =	&Param;
	dispParams.cNamedArgs = 0;
	dispParams.rgdispidNamedArgs = NULL;

	return dispParams;
}

void CWordProxy::SetProperty(IDispatch* pIDispatch, const CComBSTR& PropName, const CComVariant& Value)
{
	_ASSERT( pIDispatch != NULL );

	DISPID PropDispId = GetDispID(pIDispatch, PropName); 
	DISPID DispIdNamedArgs = DISPID_PROPERTYPUT;

	CComVariant ValueCopy(Value); 
	DISPPARAMS DispParams = {0};

    DispParams.cArgs = 1;
    DispParams.rgvarg =	&ValueCopy;
    DispParams.cNamedArgs =	1;
    DispParams.rgdispidNamedArgs = &DispIdNamedArgs;
    
    HRESULT hr = pIDispatch->Invoke(PropDispId, IID_NULL, GetUserDefaultLCID(),
										   DISPATCH_PROPERTYPUT, &DispParams, NULL, NULL, NULL);
	if (hr != S_OK)
		throw EInvocationError(hr);
}

void CWordProxy::GetProperty(IDispatch* pIDispatch, const CComBSTR& PropName, CComVariant& Value)
{
	_ASSERT( pIDispatch != NULL );

	DISPID PropDispId = GetDispID(pIDispatch, PropName); 
	DISPPARAMS DispParams = {0};
	HRESULT hr = pIDispatch->Invoke(PropDispId, IID_NULL, GetUserDefaultLCID(),
										   DISPATCH_PROPERTYGET, &DispParams, &Value, NULL, NULL);
	if (hr != S_OK)
		throw EInvocationError(hr);
}

void CWordProxy::CallMethod(IDispatch* pIDispatch, const CComBSTR& ProcName )
{
	DISPPARAMS DispParams = {0};
	CComVariant Result;
	CallMethod(pIDispatch, ProcName, &DispParams, Result);
}

void CWordProxy::CallMethod(IDispatch* pIDispatch, const CComBSTR& ProcName, CComVariant& Result)
{
	DISPPARAMS DispParams = {0};
	CallMethod(pIDispatch, ProcName, &DispParams, Result); 
}

void CWordProxy::CallMethod(IDispatch* pIDispatch, const CComBSTR& ProcName, DISPPARAMS* pDispParams)
{
	CComVariant Result;
	CallMethod(pIDispatch, ProcName, pDispParams, Result);
}

void CWordProxy::CallMethod(IDispatch* pIDispatch, const CComBSTR& ProcName, DISPPARAMS* pDispParams, CComVariant& Result)
{
	_ASSERT( pIDispatch != NULL );

	DISPID MethodDispId = GetDispID(pIDispatch, ProcName); 
	HRESULT hr = pIDispatch->Invoke(MethodDispId, IID_NULL, GetUserDefaultLCID(),
										   DISPATCH_METHOD, pDispParams, &Result, NULL, NULL);
	if (hr != S_OK)
		throw EInvocationError(hr);
}

void CWordProxy::Finalize()
{
	if( m_WordApplication != NULL)
	{
		if( m_Document != NULL )
			m_Document.Release();
		try
		{
			CComVariant SaveOptions  = wdDoNotSaveChanges;
			DISPPARAMS Params = CreateDispParams(SaveOptions);
			CallMethod(m_WordApplication, L"Quit", &Params);
		}
		catch(EBaseWordError)
		{
		}
		m_WordApplication.Release();
	}
}

void CWordProxy::NewDocument()
{
	_ASSERT( m_WordApplication != NULL);
	_ASSERT( m_Document == NULL );

	CComVariant Documents;
	GetProperty( m_WordApplication, L"Documents", Documents);
	CComVariant NewDocument;
	CallMethod( Documents.pdispVal, L"Add", NewDocument);
	m_Document = NewDocument.pdispVal;
}

void CWordProxy::SaveAs(LPCTSTR PathToFile)
{
	_ASSERT( m_Document != NULL );
	
	CComVariant vPathToFile = PathToFile;
	DISPPARAMS Params = CreateDispParams(vPathToFile);

	CallMethod( m_Document, L"SaveAs", &Params );
}

void CWordProxy::PastePicture(LPCTSTR PathToFile)
{
	_ASSERT( m_Document != NULL );
	
	CComVariant vPathToFile = PathToFile;
	DISPPARAMS Params = CreateDispParams(vPathToFile);
	
	CComVariant InlineShapes;
	GetProperty( m_Document, L"InlineShapes", InlineShapes);
	
	CComVariant Picture;
	CallMethod(InlineShapes.pdispVal, L"AddPicture", &Params, Picture);

	SetPictureStyle(Picture.pdispVal);
}

void CWordProxy::SetPictureStyle(IDispatch* Picture)
{
	_ASSERT( Picture != NULL );

	CComVariant Borders;
	GetProperty(Picture, L"Borders", Borders);

	SetProperty(Borders.pdispVal, L"Enable", true);
	SetProperty(Borders.pdispVal, L"OutsideLineStyle", wdLineStyleDashLargeGap );
	SetProperty(Borders.pdispVal, L"OutsideColor", wdColorBlack );
}

void CWordProxy::GetMarginsInPt(DOCUMENT_MARGINS& Margins)
{
	_ASSERT( m_Document != NULL );

	CComVariant PageSetup;
	GetProperty(m_Document, L"PageSetup", PageSetup);
	
	CComVariant LeftMargin;
	GetProperty(PageSetup.pdispVal, L"LeftMargin", LeftMargin);
	CComVariant RightMargin;
	GetProperty(PageSetup.pdispVal, L"RightMargin", RightMargin);
	CComVariant TopMargin;
	GetProperty(PageSetup.pdispVal, L"TopMargin", TopMargin);
	CComVariant BottomMargin;
	GetProperty(PageSetup.pdispVal, L"BottomMargin", BottomMargin);

	Margins.Left = LeftMargin.fltVal;
	Margins.Right = RightMargin.fltVal;
	Margins.Top = TopMargin.fltVal;
	Margins.Bottom = BottomMargin.fltVal;
}

void CWordProxy::GetPageSizeInPt(DOCUMENT_PAGE_SIZE& PageSize)
{
	_ASSERT( m_Document != NULL );

	CComVariant PageSetup;
	GetProperty(m_Document, L"PageSetup", PageSetup);

	CComVariant Height;
	GetProperty(PageSetup.pdispVal, L"PageHeight", Height);
	CComVariant Width;
	GetProperty(PageSetup.pdispVal, L"PageWidth", Width);

	PageSize.Height = Height.fltVal;
	PageSize.Width = Width.fltVal;
}

LONG CWordProxy::PointsToPixels(FLOAT Pt, bool Vertical)
{
	_ASSERT( m_WordApplication != NULL );
	VARIANT Params[2];
	ZeroMemory(Params, sizeof(Params) );

	CComVariant vPt = Pt;
	CComVariant vVertical = Vertical;
	// safecall, arguments in reverse order
	Params[1] = (VARIANT)vPt;
	Params[0] = (VARIANT)vVertical;
	
	DISPPARAMS DispParams = {0};
	DispParams.cArgs = 2;
	DispParams.rgvarg = Params;
	DispParams.cNamedArgs = 0;
	DispParams.rgdispidNamedArgs = NULL;

	CComVariant Result;
	CallMethod( m_WordApplication, L"PointsToPixels", &DispParams, Result);
	
	Result.ChangeType(VT_I4);
	return Result.lVal;
}

void CWordProxy::PageBreakAndUP()
{
	CComVariant Selection;
	GetProperty(m_WordApplication, _T("Selection"), Selection);

	CComVariant vBreakType = wdPageBreak;
	DISPPARAMS Params = CreateDispParams(vBreakType);

	CallMethod(Selection.pdispVal, _T("InsertBreak"), &Params);

	CallMethod(Selection.pdispVal, _T("MoveUp") );

}

void CWordProxy::Test()
{
	NewDocument();
	SetProperty(m_WordApplication, L"Visible", true);

	/*PastePicture(_T("C:\\Users\\1\\Pictures\\imageboards\\0chan\\12397413931.jpg"));
	PastePicture(_T("C:\\Users\\1\\Pictures\\imageboards\\0chan\\12397413931.jpg"));
	PastePicture(_T("C:\\Users\\1\\Pictures\\imageboards\\0chan\\12397413931.jpg"));
	SaveAs(_T("C:\\TEMP\\MyDoc.doc"));*/
	PastePicture(_T("C:\\Temp\\splitted\\image0010.jpg"));
	
	CComVariant Selection;
	GetProperty(m_WordApplication, _T("Selection"), Selection);

	CComVariant vBreakType = wdPageBreak;
	DISPPARAMS Params = CreateDispParams(vBreakType);

	CallMethod(Selection.pdispVal, _T("InsertBreak"), &Params);

	CallMethod(Selection.pdispVal, _T("MoveUp") );

	PastePicture(_T("C:\\Temp\\splitted\\image0009.jpg"));

	CallMethod(Selection.pdispVal, _T("InsertBreak"), &Params);

	CallMethod(Selection.pdispVal, _T("MoveUp") );
	
	PastePicture(_T("C:\\Temp\\splitted\\image0008.jpg"));

	CallMethod(Selection.pdispVal, _T("InsertBreak"), &Params);

	CallMethod(Selection.pdispVal, _T("MoveUp") );
	
	PastePicture(_T("C:\\Temp\\splitted\\image0007.jpg"));

	CallMethod(Selection.pdispVal, _T("InsertBreak"), &Params);

	CallMethod(Selection.pdispVal, _T("MoveUp") );
	
	PastePicture(_T("C:\\Temp\\splitted\\image0006.jpg"));

	CallMethod(Selection.pdispVal, _T("InsertBreak"), &Params);

	CallMethod(Selection.pdispVal, _T("MoveUp") );
	
	PastePicture(_T("C:\\Temp\\splitted\\image0005.jpg"));

	CallMethod(Selection.pdispVal, _T("InsertBreak"), &Params);

	CallMethod(Selection.pdispVal, _T("MoveUp") );
	
	PastePicture(_T("C:\\Temp\\splitted\\image0004.jpg"));

	CallMethod(Selection.pdispVal, _T("InsertBreak"), &Params);

	CallMethod(Selection.pdispVal, _T("MoveUp") );
	
	PastePicture(_T("C:\\Temp\\splitted\\image0003.jpg"));

	CallMethod(Selection.pdispVal, _T("InsertBreak"), &Params);

	CallMethod(Selection.pdispVal, _T("MoveUp") );
	
	PastePicture(_T("C:\\Temp\\splitted\\image0002.jpg"));

	CallMethod(Selection.pdispVal, _T("InsertBreak"), &Params);

	CallMethod(Selection.pdispVal, _T("MoveUp") );
	
	PastePicture(_T("C:\\Temp\\splitted\\image0001.jpg"));

	SaveAs(_T("C:\\TEMP\\MyDoc.doc"));
}